﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;

namespace YArchitech.Controls
{
	public class GZip
	{
		public static GZipResult Compress(string lpSourceFolder, string lpDestFolder, string zipFileName)
		{
			return GZip.Compress(lpSourceFolder, "*.*", SearchOption.AllDirectories, lpDestFolder, zipFileName, true);
		}

		public static GZipResult Compress(string lpSourceFolder, string searchPattern, SearchOption searchOption, string lpDestFolder, string zipFileName, bool deleteTempFile)
		{
			return GZip.Compress(new DirectoryInfo(lpSourceFolder).GetFiles("*.*", searchOption), lpSourceFolder, lpDestFolder, zipFileName, deleteTempFile);
		}

		public static GZipResult Compress(FileInfo[] files, string[] folders, string lpBaseFolder, string lpDestFolder, string zipFileName)
		{
			IList<FileInfo> list = new List<FileInfo>();
			foreach (FileInfo item in files)
			{
				list.Add(item);
			}
			for (int i = 0; i < folders.Length; i++)
			{
				foreach (FileInfo item2 in new DirectoryInfo(folders[i]).GetFiles("*.*", SearchOption.AllDirectories))
				{
					list.Add(item2);
				}
			}
			return GZip.Compress(list.ToArray<FileInfo>(), lpBaseFolder, lpDestFolder, zipFileName, true);
		}

		public static GZipResult Compress(FileInfo[] files, string lpBaseFolder, string lpDestFolder, string zipFileName)
		{
			return GZip.Compress(files, lpBaseFolder, lpDestFolder, zipFileName, true);
		}

		public static GZipResult Compress(FileInfo[] files, string lpBaseFolder, string lpDestFolder, string zipFileName, bool deleteTempFile)
		{
			GZipResult gzipResult = new GZipResult();
			try
			{
				if (!lpDestFolder.EndsWith("\\"))
				{
					lpDestFolder += "\\";
				}
				string text = lpDestFolder + zipFileName + ".tmp";
				string text2 = lpDestFolder + zipFileName;
				gzipResult.TempFile = text;
				gzipResult.ZipFile = text2;
				if (files != null && files.Length != 0)
				{
					GZip.CreateTempFile(files, lpBaseFolder, text, gzipResult);
					if (gzipResult.FileCount > 0)
					{
						GZip.CreateZipFile(text, text2, gzipResult);
					}
					if (deleteTempFile)
					{
						File.Delete(text);
						gzipResult.TempFileDeleted = true;
					}
				}
			}
			catch
			{
				gzipResult.Errors = true;
			}
			return gzipResult;
		}

		private static void CreateZipFile(string lpSourceFile, string lpZipFile, GZipResult result)
		{
			FileStream fileStream = null;
			FileStream fileStream2 = null;
			GZipStream gzipStream = null;
			try
			{
				fileStream = new FileStream(lpZipFile, FileMode.Create, FileAccess.Write, FileShare.None);
				gzipStream = new GZipStream(fileStream, CompressionMode.Compress, true);
				fileStream2 = new FileStream(lpSourceFile, FileMode.Open, FileAccess.Read, FileShare.Read);
				byte[] array = new byte[fileStream2.Length];
				fileStream2.Read(array, 0, array.Length);
				fileStream2.Close();
				fileStream2 = null;
				gzipStream.Write(array, 0, array.Length);
				result.ZipFileSize = fileStream.Length;
				result.CompressionPercent = GZip.GetCompressionPercent(result.TempFileSize, result.ZipFileSize);
			}
			catch
			{
				result.Errors = true;
			}
			finally
			{
				if (gzipStream != null)
				{
					gzipStream.Close();
					gzipStream = null;
				}
				if (fileStream != null)
				{
					fileStream.Close();
					fileStream = null;
				}
				if (fileStream2 != null)
				{
					fileStream2.Close();
					fileStream2 = null;
				}
			}
		}

		private static void CreateTempFile(FileInfo[] files, string lpBaseFolder, string lpTempFile, GZipResult result)
		{
			int num = 0;
			FileStream fileStream = null;
			FileStream fileStream2 = null;
			if (files != null && files.Length != 0)
			{
				try
				{
					result.Files = new GZipFileInfo[files.Length];
					fileStream = new FileStream(lpTempFile, FileMode.Create, FileAccess.Write, FileShare.None);
					foreach (FileInfo fileInfo in files)
					{
						fileInfo.DirectoryName + "\\";
						try
						{
							GZipFileInfo gzipFileInfo = new GZipFileInfo();
							gzipFileInfo.Index = num;
							string fullName = fileInfo.FullName;
							gzipFileInfo.LocalPath = fullName;
							string text = fullName.Replace(lpBaseFolder, string.Empty);
							text = text.Replace("\\", "/");
							gzipFileInfo.RelativePath = text;
							fileStream2 = new FileStream(fullName, FileMode.Open, FileAccess.Read, FileShare.Read);
							byte[] array = new byte[fileStream2.Length];
							fileStream2.Read(array, 0, array.Length);
							fileStream2.Close();
							fileStream2 = null;
							string text2 = fileInfo.LastWriteTimeUtc.ToString();
							gzipFileInfo.ModifiedDate = fileInfo.LastWriteTimeUtc;
							gzipFileInfo.Length = array.Length;
							string s = string.Concat(new string[]
							{
								num.ToString(),
								",",
								text,
								",",
								text2,
								",",
								array.Length.ToString(),
								"\n"
							});
							byte[] bytes = Encoding.Default.GetBytes(s);
							fileStream.Write(bytes, 0, bytes.Length);
							fileStream.Write(array, 0, array.Length);
							fileStream.WriteByte(10);
							gzipFileInfo.AddedToTempFile = true;
							result.Files[num] = gzipFileInfo;
							num++;
						}
						catch
						{
							result.Errors = true;
						}
						finally
						{
							if (fileStream2 != null)
							{
								fileStream2.Close();
								fileStream2 = null;
							}
						}
						if (fileStream != null)
						{
							result.TempFileSize = fileStream.Length;
						}
					}
				}
				catch
				{
					result.Errors = true;
				}
				finally
				{
					if (fileStream != null)
					{
						fileStream.Close();
						fileStream = null;
					}
				}
			}
			result.FileCount = num;
		}

		public static GZipResult Decompress(string lpSourceFolder, string lpDestFolder, string zipFileName)
		{
			return GZip.Decompress(lpSourceFolder, lpDestFolder, zipFileName, true, true, null, null, 4096);
		}

		public static GZipResult Decompress(string lpSourceFolder, string lpDestFolder, string zipFileName, bool writeFiles, string addExtension)
		{
			return GZip.Decompress(lpSourceFolder, lpDestFolder, zipFileName, true, writeFiles, addExtension, null, 4096);
		}

		public static GZipResult Decompress(string lpSrcFolder, string lpDestFolder, string zipFileName, bool deleteTempFile, bool writeFiles, string addExtension, Hashtable htFiles, int bufferSize)
		{
			GZipResult gzipResult = new GZipResult();
			if (!lpSrcFolder.EndsWith("\\"))
			{
				lpSrcFolder += "\\";
			}
			if (!lpDestFolder.EndsWith("\\"))
			{
				lpDestFolder += "\\";
			}
			string text = lpSrcFolder + zipFileName + ".tmp";
			string text2 = lpSrcFolder + zipFileName;
			gzipResult.TempFile = text;
			gzipResult.ZipFile = text2;
			FileStream fileStream = null;
			ArrayList arrayList = new ArrayList();
			if (string.IsNullOrEmpty(addExtension))
			{
				addExtension = string.Empty;
			}
			else if (!addExtension.StartsWith("."))
			{
				addExtension = "." + addExtension;
			}
			try
			{
				fileStream = GZip.UnzipToTempFile(text2, text, gzipResult);
				if (fileStream != null)
				{
					while (fileStream.Position != fileStream.Length)
					{
						string text3 = null;
						while (string.IsNullOrEmpty(text3) && fileStream.Position != fileStream.Length)
						{
							text3 = GZip.ReadLine(fileStream);
						}
						if (!string.IsNullOrEmpty(text3))
						{
							GZipFileInfo gzipFileInfo = new GZipFileInfo();
							if (gzipFileInfo.ParseFileInfo(text3) && gzipFileInfo.Length > 0)
							{
								arrayList.Add(gzipFileInfo);
								string text4 = lpDestFolder + gzipFileInfo.RelativePath;
								string folder = GZip.GetFolder(text4);
								gzipFileInfo.LocalPath = text4;
								bool flag = false;
								if (htFiles == null || htFiles.ContainsKey(gzipFileInfo.RelativePath))
								{
									gzipFileInfo.RestoreRequested = true;
									flag = writeFiles;
								}
								if (flag)
								{
									if (!Directory.Exists(folder))
									{
										Directory.CreateDirectory(folder);
									}
									gzipFileInfo.Restored = GZip.WriteFile(fileStream, gzipFileInfo.Length, text4 + addExtension, bufferSize);
								}
								else
								{
									fileStream.Position += (long)gzipFileInfo.Length;
								}
							}
						}
					}
				}
			}
			catch
			{
				gzipResult.Errors = true;
			}
			finally
			{
				if (fileStream != null)
				{
					fileStream.Close();
					fileStream = null;
				}
			}
			try
			{
				if (deleteTempFile)
				{
					File.Delete(text);
					gzipResult.TempFileDeleted = true;
				}
			}
			catch
			{
				gzipResult.Errors = true;
			}
			gzipResult.FileCount = arrayList.Count;
			gzipResult.Files = new GZipFileInfo[arrayList.Count];
			arrayList.CopyTo(gzipResult.Files);
			return gzipResult;
		}

		private static string ReadLine(FileStream fs)
		{
			string empty = string.Empty;
			byte[] array = new byte[4096];
			byte b = 0;
			byte b2 = 10;
			int num = 0;
			while (b != b2)
			{
				b = (byte)fs.ReadByte();
				array[num] = b;
				num++;
			}
			return Encoding.Default.GetString(array, 0, num - 1);
		}

		private static bool WriteFile(FileStream fs, int fileLength, string lpFile, int bufferSize)
		{
			bool result = false;
			FileStream fileStream = null;
			if (bufferSize == 0 || fileLength < bufferSize)
			{
				bufferSize = fileLength;
			}
			int i = fileLength;
			try
			{
				byte[] buffer = new byte[bufferSize];
				fileStream = new FileStream(lpFile, FileMode.Create, FileAccess.Write, FileShare.None);
				while (i > 0)
				{
					int count;
					if (i > bufferSize)
					{
						count = bufferSize;
					}
					else
					{
						count = i;
					}
					int num = fs.Read(buffer, 0, count);
					i -= num;
					if (num == 0)
					{
						break;
					}
					fileStream.Write(buffer, 0, num);
					fileStream.Flush();
				}
				fileStream.Flush();
				fileStream.Close();
				fileStream = null;
				result = true;
			}
			catch
			{
				result = false;
			}
			finally
			{
				if (fileStream != null)
				{
					fileStream.Flush();
					fileStream.Close();
					fileStream = null;
				}
			}
			return result;
		}

		private static string GetFolder(string lpFilePath)
		{
			string text = lpFilePath;
			int num = text.LastIndexOf("\\");
			if (num != -1)
			{
				text = text.Substring(0, num + 1);
			}
			return text;
		}

		private static FileStream UnzipToTempFile(string lpZipFile, string lpTempFile, GZipResult result)
		{
			FileStream fileStream = null;
			GZipStream gzipStream = null;
			FileStream fileStream2 = null;
			byte[] buffer = new byte[4096];
			try
			{
				fileStream = new FileStream(lpZipFile, FileMode.Open, FileAccess.Read, FileShare.Read);
				result.ZipFileSize = fileStream.Length;
				fileStream2 = new FileStream(lpTempFile, FileMode.Create, FileAccess.Write, FileShare.None);
				gzipStream = new GZipStream(fileStream, CompressionMode.Decompress, true);
				int num;
				do
				{
					num = gzipStream.Read(buffer, 0, 4096);
					if (num != 0)
					{
						fileStream2.Write(buffer, 0, num);
					}
				}
				while (num == 4096);
			}
			catch
			{
				result.Errors = true;
			}
			finally
			{
				if (gzipStream != null)
				{
					gzipStream.Close();
					gzipStream = null;
				}
				if (fileStream2 != null)
				{
					fileStream2.Close();
					fileStream2 = null;
				}
				if (fileStream != null)
				{
					fileStream.Close();
					fileStream = null;
				}
			}
			FileStream fileStream3 = new FileStream(lpTempFile, FileMode.Open, FileAccess.Read, FileShare.None);
			if (fileStream3 != null)
			{
				result.TempFileSize = fileStream3.Length;
			}
			return fileStream3;
		}

		private static int GetCompressionPercent(long tempLen, long zipLen)
		{
			double num = (double)tempLen;
			double num2 = (double)zipLen;
			double num3 = 100.0;
			return (int)((num - num2) / num * num3);
		}
	}
}
